package org.example.logic

import com.alibaba.fastjson.JSONObject
import org.example.common.Logging
import org.example.constant.{ApolloConst, RiskConst}
import org.example.dao.{AlarmEvidence, AlarmNumber, CustomAlarmEvidence, VehicleAlarmEvidence}
import org.example.enums.WarningTypeEnum
import org.example.model.MapToJson
import org.example.originUtils.BaseWarn
import org.example.utils.{EsUtils, IdWorker, KafkaUtil, SearchInfo, TransformUtils}
import org.apache.commons.collections.MapUtils
import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.time.FastDateFormat
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerRecord}
import org.joda.time.DateTime
import org.joda.time.format.{DateTimeFormat, DateTimeFormatter}
import redis.clients.jedis.Jedis

import java.util
import scala.collection.mutable.ListBuffer

/**
 * @Description 报警生成相关
 * @Date  2021/7/13
 **/
object AlarmProduce extends Logging {

  /**
   * 智能设备类报警
   *
   * @param messageInfo
   * @param jedis
   * @param esList
   * @param riskList
   */
  def smartAlarmProduce(messageInfo: JSONObject, jedis: Jedis, baseWarn: Map[String, String], esList: ListBuffer[(String, String)], riskList: ListBuffer[AlarmNumber]): Unit = {
    if (null != messageInfo && messageInfo.containsKey("warnTime") && !messageInfo.getString("warnTime").contains(":")) {
      val esMap = new util.HashMap[String, String]()//用于warninfo_index
      val warnMap = new util.HashMap[String, String]()//用于alarm_details_index
      val warnList = new ListBuffer[(String,String)]()
      //获取报警时间
      val getWarnTime = messageInfo.getString("warnTime")
      var datetime = getWarnTime
      if (getWarnTime.length == 13) {
        datetime = (getWarnTime.toLong / 1000).toString
      }
      var warnTime = getWarnTime
      if (getWarnTime.length == 10) {
        warnTime = getWarnTime + "000"
      }
      val warnSrc = messageInfo.getString("warnSrc")
      val warnType = messageInfo.getString("warnType")
      val dataType: String = messageInfo.getString("dataType")
      //报警英文名code
      val baseWarnInfo = BaseWarn.getWarnTypeByCode(warnType)
      val warnTypeCode: String = baseWarnInfo._2
      val infoId = messageInfo.getString("infoId")

      val vehicleNo: String = messageInfo.getString("vehicleNo")
      val vehicleColor: String = messageInfo.getString("vehicleColor")
      val primaryKey = vehicleNo + "#" + vehicleColor

      val appId: String = messageInfo.getString("appId")//平台id
      val businessTime: String = messageInfo.getString("businessTime")

      //车道偏离报警、分神驾驶报警和人脸识别报警存到redis,验证设备有效性
      AlarmTrigger.deviceWarnUpdate(jedis, primaryKey, warnType)
      //更新设备的最后上线时间
      val format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
      updateLastOnlineTime("lastOnlineSmartDay", primaryKey, format.format(warnTime.toLong), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"), jedis)

      //是否在监控的报警类型里面
      if (baseWarn.contains(warnTypeCode)) {
        //报警名称
        val typeName = baseWarn.getOrElse(warnTypeCode, baseWarnInfo._1)
        val day: String = getRiskCodeTime((datetime + "000").toLong)
        val alarmTime: String = getAlarmTime((datetime + "000").toLong)
        val driverInfo: util.Map[String, String] = jedis.hgetAll("driverInfo:" + primaryKey)
        val platformName: String = jedis.hget("platform",appId)//平台名称
        //驾驶员姓名
        val driverName = driverInfo.get("driverName")
        //驾驶员编码
        val driverCode = driverInfo.get("driverCode")
        //车辆所属公司编码
        val vehicleEnterpriseCode = driverInfo.get("vehicleEnterprise")
        //车辆使用性质
        val useNature = driverInfo.get("useNature")
        //车辆管控类型
        val controlType = driverInfo.get("controlType")
        //车辆所属公司社会信用代码
        val socialCreditCode = driverInfo.get("socialCreditCode")
        //车辆所属公司名称
        val enterpriseName = driverInfo.get("enterpriseName")
        //获取当前报警所属周期
        val tripStartMillis = PeriodProcess.getDrivingPeriodStart(primaryKey, warnTime.toLong, jedis)
        //速度、经纬度暂时为空
        val speed = "65.7"
        val longitude = "-"
        val latitude = "-"
        val id = primaryKey + "_" + warnTypeCode + "_" + datetime
        val tempKey = primaryKey + "_" + warnTypeCode + "_" + tripStartMillis
        //warninfo_index需要字段
        esMap.put("primaryKey", tempKey)
        esMap.put("id", id)
        esMap.put("datetime", datetime)
        esMap.put("warnSeq", "-")
        esMap.put("deviceId", "-")
        esMap.put("warnSrc", warnSrc)
        esMap.put("warnType", warnType)
        esMap.put("eventType", "-")
        esMap.put("typeName", typeName)
        esMap.put("typeCode", warnTypeCode)
        esMap.put("infoId", infoId)
        esMap.put("longitude", "-")
        esMap.put("latitude", "-")
        esMap.put("districtCode", "-")
        esMap.put("riskCodeTime", day)
        esMap.put("driverName", driverName)
        esMap.put("driverCode", driverCode)
        esMap.put("vehicleEnterpriseCode", vehicleEnterpriseCode)
        esMap.put("vehicleNo", vehicleNo)
        esMap.put("vehicleColor", vehicleColor)
        esMap.put("speed", "-")
        esMap.put("appId", appId)

        //索引alarm_details_index需要字段
        warnMap.put("id", id)
        warnMap.put("alarmId", id)
        warnMap.put("warntime", alarmTime)
        warnMap.put("warnsrc", warnSrc)
        warnMap.put("warntype", warnType)
        warnMap.put("eventtype", "-")
        warnMap.put("datatype", dataType)
        warnMap.put("warningtypename", typeName)
        warnMap.put("warningtypecode", warnTypeCode)
        warnMap.put("infoid", infoId)
        warnMap.put("longitude", "-")
        warnMap.put("latitude", "-")
        warnMap.put("districtcode", "-")
        warnMap.put("alarmday", alarmTime)
        warnMap.put("drivername", driverName)
        warnMap.put("driverid", driverCode)
        warnMap.put("enterprisecode", vehicleEnterpriseCode)
        warnMap.put("enterprisename",enterpriseName)
        warnMap.put("socialcreditcode",socialCreditCode)
        warnMap.put("vehicleno", vehicleNo)
        warnMap.put("vehiclecolor", vehicleColor)
        warnMap.put("appid", appId)
        warnMap.put("platformname", platformName)
        warnMap.put("businesstime",businessTime)
        warnMap.put("usenature",useNature)

        warnList += ((id, MapToJson.Map2Josn(warnMap)))
        //此处将原来alarm_details_index备份至alarm_details_index_bak中
        EsUtils.insertBulk("alarm_details_index", "alarm_details_type", warnList)
        //智能设备报警发送至kafka，供企业设备数据录入统计用
        val kafkaProducer: KafkaProducer[String, String] = KafkaUtil.getKafkaProducer(ApolloConst.bootstrap)
        kafkaProducer.send(new ProducerRecord("alarm_details_topic",MapToJson.Map2Josn(warnMap)))

        esList += ((id, MapToJson.Map2Josn(esMap)))

        //设备报警生成时将报警的信息存入缓存中
        if (StringUtils.isNotEmpty(warnTypeCode)) {
          //缓存报警证据
          val evidenceKey = "riskTimes:" + primaryKey + "_" + tripStartMillis
          val evidence = AlarmEvidence(id, datetime, 0)
          PeriodProcess.updatePeriodWarnTimes(evidenceKey, warnTypeCode, evidence, jedis)
          val currentCar: util.Map[String, String] = jedis.hgetAll(evidenceKey)
          riskList += (AlarmNumber(currentCar, vehicleNo, vehicleColor, speed, longitude, latitude, warnTime, useNature, controlType, tripStartMillis.toString, List(warnTypeCode)))
        }
      }
    }
  }

  /**
   * 自定义类报警
   *
   * @param messageInfo    定位信息
   * @param jedis          jedis
   *                       //   * @param platformVehNos 通涌部标的车牌号
   * @param baseWarn       基础报警code码
   * @param riskTimeDeploy 夜间时段
   * @param esList         报警list
   * @param riskList       风险list
   */
  def customAlarmProduce(messageInfo: JSONObject,
                         jedis: Jedis,
                         // platformVehNos: mutable.Buffer[String],
                         baseWarn: Map[String, String],
                         riskTimeDeploy: (Int, Int),
                         esList: ListBuffer[(String, String)],
                         riskList: ListBuffer[AlarmNumber]): Unit = {
    //    if (!(platformVehNos.contains(messageInfo.getString("vehicleNo")) && messageInfo.getString("appId").startsWith("1"))) {
    if (null != messageInfo && messageInfo.containsKey("vec1") ) {
    val formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    val vehicleNo: String = messageInfo.getString("vehicleNo")
    val vehicleColor: String = messageInfo.getString("vehicleColor")
    val primaryKey = vehicleNo + "#" + vehicleColor
    warn("primaryKey"+primaryKey)
    val dateTime: String = messageInfo.getString("dateTime")
    val lng = messageInfo.getString("lon").toDouble * 0.000001
    val lat = messageInfo.getString("lat").toDouble * 0.000001
    //WGS84(地球坐标系)转GCj02(火星坐标系)
    val transform = TransformUtils.wgs84togcj02(lng, lat)
    val longitude = transform._1.formatted("%.6f")
    val latitude = transform._2.formatted("%.6f")

    val vec1: String = messageInfo.getString("vec1")
    val vec2: String = messageInfo.getString("vec2")
    val vec3: String = messageInfo.getString("vec3")
    val warnTypeCodeList = new ListBuffer[String]()
    val speed = vec1
    val times: DateTime = DateTime.parse(dateTime, formatter)
    val warnTime: Long = times.toDate.getTime
    val time: String = getRiskCodeTime(warnTime)
    val datetime = (warnTime / 1000).toString
    val appId: String = messageInfo.getString("appId")
    val alarmTime = dateTime
    val businessTime: String = messageInfo.getString("businessTime")
    val dataType: String = messageInfo.getString("dataType")

    val platformName: String = jedis.hget("platform",appId)//平台名称

    // 行驶周期的计算
    val periodStatus = PeriodProcess.drivingPeriod(messageInfo, jedis)
    // 连续驾驶详情
    PeriodProcess.drivingContinued(messageInfo, jedis)

    //驾驶员姓名
    var driverName = ""
    //驾驶员编码
    var driverCode = ""
    //车辆所属公司编码
    var vehicleEnterpriseCode = ""
    //车辆使用性质
    var useNature = ""
    //车辆管控类型
    var controlType = ""
    //车辆所属公司社会信用代码
    var socialCreditCode = ""
    //车辆所属公司名称
    var enterpriseName = ""
    val driverInfo: util.Map[String, String] = jedis.hgetAll("driverInfo:" + primaryKey)
    if (MapUtils.isNotEmpty(driverInfo)) {
      //驾驶员姓名
      driverName = driverInfo.get("driverName")
      //驾驶员编码
      driverCode = driverInfo.get("driverCode")
      //车辆所属公司编码
      vehicleEnterpriseCode = driverInfo.get("vehicleEnterprise")
      //车辆使用性质
      useNature = driverInfo.get("useNature")
      //车辆管控类型
      controlType = driverInfo.get("controlType")
      //车辆所属公司社会信用代码
      socialCreditCode = driverInfo.get("socialCreditCode")
      //车辆所属公司名称
      enterpriseName = driverInfo.get("enterpriseName")
    }

    //统计企业和车辆驾驶时长？？
    EnterpriseDrivingProcess.enterpriseDrivingTimes(primaryKey, dateTime, speed, vehicleEnterpriseCode, jedis)

    //将车牌号+颜色以及时间存到redis-->更新设备的最后上线时间
    if (StringUtils.isNotEmpty(vehicleNo) && StringUtils.isNotEmpty(vehicleColor)) {
      //GPS设备存储
      updateLastOnlineTime("lastOnlineGpsDay", primaryKey, dateTime, formatter, jedis)
    }

    //获取当前报警所属周期-->根据车牌号和车牌颜色及报警时间查询当前行驶周期开始时间
    val tripStartMillis = PeriodProcess.getDrivingPeriodStart(primaryKey, warnTime, jedis)

    //报警基本信息
    val customAlarmEvidence = CustomAlarmEvidence(primaryKey, vehicleNo, vehicleColor, longitude, latitude, speed, driverName, driverCode, vehicleEnterpriseCode,
      datetime, time, appId, socialCreditCode, enterpriseName,dataType, alarmTime, businessTime, useNature,platformName, tripStartMillis)

    if (periodStatus._1) {
      //ADAS设备有效性报警
      val lastTripStartMillis = DateTime.parse(periodStatus._2, formatter).getMillis
      val format = FastDateFormat.getInstance("yyyyMMdd")
      val tripDay = format.format(tripStartMillis)
      val equipmentWarnCodeList = new ListBuffer[String]()
      val vehicleAlarmEvidences = new ListBuffer[VehicleAlarmEvidence]()

      val customPeriodAlarmEvidence = CustomAlarmEvidence(primaryKey, vehicleNo, vehicleColor, longitude, latitude, speed, driverName, driverCode, vehicleEnterpriseCode,
        datetime, time, appId, socialCreditCode, enterpriseName,dataType: String, alarmTime, businessTime, useNature,platformName, lastTripStartMillis)
      if (baseWarn.contains(WarningTypeEnum.ADAS_DEVICE_VALIDITY_ALARM.toString)
        && AlarmTrigger.equipmentWarnValid(jedis, "adasDevice", primaryKey, periodStatus._3, periodStatus._4)) {
        val warnTypeCode = WarningTypeEnum.ADAS_DEVICE_VALIDITY_ALARM.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "ADAS设备有效性报警")

        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, periodStatus._3, customPeriodAlarmEvidence,
          equipmentWarnCodeList, esList, vehicleAlarmEvidences, periodStatus._3.toString, periodStatus._4.toString)
      }
      //DSM设备有效性报警
      if (baseWarn.contains(WarningTypeEnum.DSM_DEVICE_VALIDITY_ALARM.toString) &&
        AlarmTrigger.equipmentWarnValid(jedis, "dsmDevice", primaryKey, periodStatus._3, periodStatus._4)) {
        val warnTypeCode = WarningTypeEnum.DSM_DEVICE_VALIDITY_ALARM.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "DSM设备有效性报警")

        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, periodStatus._3, customPeriodAlarmEvidence,
          equipmentWarnCodeList, esList, vehicleAlarmEvidences, periodStatus._3.toString, periodStatus._4.toString)
      }
      //DSM设备人脸识别有效性异常
      if (baseWarn.contains(WarningTypeEnum.DRIVER_FACIAL_RECOGNITION_DEVICE_ABNORMAL.toString) &&
        AlarmTrigger.equipmentWarnValid(jedis, "driverFacialRecognition", primaryKey, periodStatus._3, periodStatus._4)) {
        val warnTypeCode = WarningTypeEnum.DRIVER_FACIAL_RECOGNITION_DEVICE_ABNORMAL.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "驾驶人人脸识别设备异常报警")

        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, periodStatus._3, customPeriodAlarmEvidence,
          equipmentWarnCodeList, esList, vehicleAlarmEvidences, periodStatus._3.toString, periodStatus._4.toString)
      }
      //设备有效性报警
      if (!equipmentWarnCodeList.isEmpty) {
        //存当前周期的报警id和时间及驾驶时长且设置过期时间为当天
        val alarmEvidenceKey = "riskTimes:" + primaryKey + "_" + tripDay
        PeriodProcess.updatePeriodWarnTimes(alarmEvidenceKey, vehicleAlarmEvidences, jedis, true)

        val currentCar: util.Map[String, String] = jedis.hgetAll(alarmEvidenceKey)
        riskList += (AlarmNumber(currentCar, vehicleNo, vehicleColor, speed, longitude, latitude, warnTime.toString, useNature, controlType, tripDay, equipmentWarnCodeList.toList))
      }
    }
    //报警证据
    val vehicleAlarmEvidences = new ListBuffer[VehicleAlarmEvidence]()
    //百码超速报警
    if (baseWarn.contains(WarningTypeEnum.ONE_HUNDRED_YARD_SPEED.toString) &&
      AlarmTrigger.isOverspeed(speed, RiskConst.ONE_HUNDRED_THRESHOLD)) {
      val warnTypeCode = WarningTypeEnum.ONE_HUNDRED_YARD_SPEED.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "百码超速报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }
    //连续百码超速报警
    if (baseWarn.contains(WarningTypeEnum.CONTINUOUS_HUNDRED_YARDS_SPEEDING.toString)) {
      val awayshundredwarn = AlarmTrigger.isOverspeedContinuous(speed, RiskConst.ONE_HUNDRED_THRESHOLD, primaryKey, dateTime, messageInfo,
        "warnhundred", RiskConst.INTERVAL_PERIOD_FORTY_SECOND, jedis)
      if (awayshundredwarn._1) {
        val warnTypeCode = WarningTypeEnum.CONTINUOUS_HUNDRED_YARDS_SPEEDING.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续百码超速报警")

        //上次报警信息
        val lastAlarm = lastCustomAlarmEvidence(awayshundredwarn._2, primaryKey, vehicleNo, vehicleColor, driverName, driverCode, vehicleEnterpriseCode,
                                                  appId, socialCreditCode, enterpriseName, dataType,alarmTime, businessTime, useNature,platformName, tripStartMillis)
        //组装报警
        assemblyEvidence(warnTypeCode, warnTypeName, 0, List(lastAlarm, customAlarmEvidence), warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }
    //夜间八十码超速报警
    if (baseWarn.contains(WarningTypeEnum.YARD_SPEEDING_ALARM_AT_NIGHT.toString) &&
      AlarmTrigger.isOverspeed(speed, RiskConst.EIGHTY_THRESHOLD, dateTime, riskTimeDeploy)) {
      val warnTypeCode = WarningTypeEnum.YARD_SPEEDING_ALARM_AT_NIGHT.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "夜间八十码超速报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }
    //连续夜间八十码超速报警
    if (baseWarn.contains(WarningTypeEnum.CONTINUOUS_EIGHTY_YARDS_SPEEDING_AT_NIGHT.toString)) {
      val nigtspeed80 = AlarmTrigger.isOverspeedContinuous(speed, RiskConst.EIGHTY_THRESHOLD, primaryKey, dateTime, messageInfo,
        "night80warn", RiskConst.INTERVAL_PERIOD_FORTY_SECOND, jedis, riskTimeDeploy)
      if (nigtspeed80._1) {
        val warnTypeCode = WarningTypeEnum.CONTINUOUS_EIGHTY_YARDS_SPEEDING_AT_NIGHT.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续夜间80码超速报警")

        val lastAlarm = lastCustomAlarmEvidence(nigtspeed80._2, primaryKey, vehicleNo, vehicleColor,
          driverName, driverCode, vehicleEnterpriseCode, appId, socialCreditCode, enterpriseName,dataType,alarmTime, businessTime, useNature,platformName, tripStartMillis)
        assemblyEvidence(warnTypeCode, warnTypeName, 0, List(lastAlarm, customAlarmEvidence), warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }

    //八十码超速报警
    if (baseWarn.contains(WarningTypeEnum.EIGHTY_YARD_SPEED.toString) &&
      AlarmTrigger.isOverspeed(speed, RiskConst.EIGHTY_THRESHOLD)) {
      val warnTypeCode = WarningTypeEnum.EIGHTY_YARD_SPEED.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "八十码超速报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }

    //连续八十码超速报警
    //  warn80--上条gps数据|本行驶周期起始时间
    if (baseWarn.contains(WarningTypeEnum.CONTINUOUS_EIGHTY_YARDS_SPEEDING.toString)) {
      val awaysEightyWarn = AlarmTrigger.isOverspeedContinuous(speed, RiskConst.EIGHTY_THRESHOLD, primaryKey, dateTime, messageInfo,
        "warn80", RiskConst.INTERVAL_PERIOD_FORTY_SECOND, jedis)
      if (awaysEightyWarn._1) {
        val warnTypeCode = WarningTypeEnum.CONTINUOUS_EIGHTY_YARDS_SPEEDING.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续八十码超速报警")

        val lastAlarm = lastCustomAlarmEvidence(awaysEightyWarn._2, primaryKey, vehicleNo, vehicleColor,
          driverName, driverCode, vehicleEnterpriseCode, appId, socialCreditCode, enterpriseName,dataType,alarmTime, businessTime, useNature,platformName, tripStartMillis)
        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, 0, List(lastAlarm, customAlarmEvidence), warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }

    //夜间六十码超速报警
    if (baseWarn.contains(WarningTypeEnum.SIXTY_YARD_SPEEDING_ALARM_AT_NIGHT.toString) &&
      AlarmTrigger.isOverspeed(speed, RiskConst.SIXTY_THRESHOLD, dateTime, riskTimeDeploy)) {
      val warnTypeCode = WarningTypeEnum.SIXTY_YARD_SPEEDING_ALARM_AT_NIGHT.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "夜间六十码超速报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }

    //连续夜间六十码超速报警
    if (baseWarn.contains(WarningTypeEnum.CONTINUOUS_SIXTY_YARDS_SPEEDING_AT_NIGHT.toString)) {
      val nigtSpeed60 = AlarmTrigger.isOverspeedContinuous(speed, RiskConst.SIXTY_THRESHOLD, primaryKey, dateTime, messageInfo,
        "night60warn", RiskConst.INTERVAL_PERIOD_FORTY_SECOND, jedis, riskTimeDeploy)
      if (nigtSpeed60._1) {
        val warnTypeCode = WarningTypeEnum.CONTINUOUS_SIXTY_YARDS_SPEEDING_AT_NIGHT.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续夜间六十码超速报警")

        val lastAlarm = lastCustomAlarmEvidence(nigtSpeed60._2, primaryKey, vehicleNo, vehicleColor,
          driverName, driverCode, vehicleEnterpriseCode, appId, socialCreditCode, enterpriseName,dataType,alarmTime, businessTime, useNature,platformName, tripStartMillis)
        assemblyEvidence(warnTypeCode, warnTypeName, 0, List(lastAlarm, customAlarmEvidence), warnTypeCodeList, esList, vehicleAlarmEvidences)

      }
    }

    //一百二十码超速报警
    if (baseWarn.contains(WarningTypeEnum.ONE_HUNDRED_AND_TWENTY_YARDSPEED.toString) &&
      AlarmTrigger.isOverspeed(speed, RiskConst.ONE_HUNDRED_AND_TWENTY_THRESHOLD, dateTime, riskTimeDeploy)) {
      val warnTypeCode = WarningTypeEnum.ONE_HUNDRED_AND_TWENTY_YARDSPEED.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "一百二十码超速报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }

    //连续一百二十码超速报警
    if (baseWarn.contains(WarningTypeEnum.CONTINUOUS_ONE_HUNDRED_AND_TWENTY_YARDS_SPEEDING.toString)) {
      val oneHundredAndTwentySpeed = AlarmTrigger.isOverspeedContinuous(speed, RiskConst.ONE_HUNDRED_AND_TWENTY_THRESHOLD, primaryKey, dateTime, messageInfo,
        "warn120", RiskConst.INTERVAL_PERIOD_FORTY_SECOND, jedis, riskTimeDeploy)
      if (oneHundredAndTwentySpeed._1) {
        val warnTypeCode = WarningTypeEnum.CONTINUOUS_ONE_HUNDRED_AND_TWENTY_YARDS_SPEEDING.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续一百二十码超速报警")
        //组合报警
        val lastAlarm = lastCustomAlarmEvidence(oneHundredAndTwentySpeed._2, primaryKey, vehicleNo, vehicleColor,
          driverName, driverCode, vehicleEnterpriseCode, appId, socialCreditCode, enterpriseName,dataType,alarmTime, businessTime, useNature,platformName, tripStartMillis)
        assemblyEvidence(warnTypeCode, warnTypeName, 0, List(lastAlarm, customAlarmEvidence), warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }

    //连续驾驶4小时超时报警
    if (baseWarn.contains(WarningTypeEnum.OVERTIME_ALARM_FOR_4HOURS_OF_CONTINUOUS_DRIVING.toString)) {
      val driver4hour = AlarmTrigger.driver4hour(dateTime, primaryKey, speed, jedis)
      if (driver4hour._1) {
        val warnTypeCode = WarningTypeEnum.OVERTIME_ALARM_FOR_4HOURS_OF_CONTINUOUS_DRIVING.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "连续4小时超时报警")

        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, driver4hour._2, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }

    //夜间连续驾驶2小时超时报警
    if (baseWarn.contains(WarningTypeEnum.OVERTIME_ALARM_FOR_2HOURS_OF_CONTINUOUS_DRIVING_AT_NIGHT.toString)) {
      val nightDriver2hour = AlarmTrigger.nightDriver2hour(dateTime, primaryKey, speed, jedis, riskTimeDeploy)
      if (nightDriver2hour._1) {
        val warnTypeCode = WarningTypeEnum.OVERTIME_ALARM_FOR_2HOURS_OF_CONTINUOUS_DRIVING_AT_NIGHT.toString
        val warnTypeName = baseWarn.getOrElse(warnTypeCode, "夜间连续2小时超时报警")

        //组合报警
        assemblyEvidence(warnTypeCode, warnTypeName, nightDriver2hour._2, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
      }
    }

    //2-5点凌晨禁行
    if (baseWarn.contains(WarningTypeEnum.CLOCK_IN_THE_MORNING_BAN.toString) &&
      AlarmTrigger.prohibitDrive(dateTime, vec1, vec2, primaryKey, vec3, longitude, latitude, jedis)) {
      val warnTypeCode = WarningTypeEnum.CLOCK_IN_THE_MORNING_BAN.toString
      val warnTypeName = baseWarn.getOrElse(warnTypeCode, "2-5点凌晨违规禁行报警")
      //组合报警
      assemblyEvidence(warnTypeCode, warnTypeName, 0, customAlarmEvidence, warnTypeCodeList, esList, vehicleAlarmEvidences)
    }

    if (!warnTypeCodeList.isEmpty) {
      //存当前周期的报警id和时间及驾驶时长
      val alarmEvidenceKey = "riskTimes:" + primaryKey + "_" + tripStartMillis
      PeriodProcess.updatePeriodWarnTimes(alarmEvidenceKey, vehicleAlarmEvidences, jedis)

      val currentCar: util.Map[String, String] = jedis.hgetAll(alarmEvidenceKey)
      riskList += (AlarmNumber(currentCar, vehicleNo, vehicleColor, speed, longitude, latitude, warnTime.toString, useNature, controlType, tripStartMillis.toString, warnTypeCodeList.toList))
    }

    //  }
    /*else if (platformVehNos.contains(messageInfo.getString("vehicleNo")) && messageInfo.getString("appId").startsWith("1")) {
      val vehicleNo: String = messageInfo.getString("vehicleNo")
      val vehicleColor: String = messageInfo.getString("vehicleColor")
      val primaryKey = vehicleNo + "#" + vehicleColor
      val dateTime: String = messageInfo.getString("dateTime")
      //将车牌号+颜色以及时间存到redis
      if (StringUtils.isNotEmpty(vehicleNo) && StringUtils.isNotEmpty(vehicleColor)) {
        //智能设备存储
        updateLastOnlineTime("lastOnlineSmartDay", primaryKey, dateTime, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"), jedis)
      }
    }*/

  }
}
  /**
   * 获取风险发生时间 生成主键用
   *
   * @return
   */
  def getRiskCodeTime(time: Long): String = {
    val format = FastDateFormat.getInstance("yyyyMMdd")
    val day = format.format(time)
    day
  }

  /**
   * @Description 获取报警发生时间
   * @Date  2021/11/3
   * @Param [time]
   * @return java.lang.String
   **/
  def getAlarmTime(time: Long): String = {
    val format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
    val warnTime = format.format(time)
    warnTime
  }

  /**
    * 更新设备的最后上线时间
    * @param key
    * @param field
    * @param dateTime
    * @param formatter
    * @param jedis
    */
  def updateLastOnlineTime(key: String, field: String, dateTime:String, formatter: DateTimeFormatter, jedis: Jedis): Unit ={
    val lastOnlineGpsStr = jedis.hget(key, field)
    if(StringUtils.isNotEmpty(lastOnlineGpsStr)){
      try{
      val lastTime = lastOnlineGpsStr.split("\\|").last
      val oldEqTime = DateTime.parse(lastTime, formatter)
      val times = DateTime.parse(dateTime, formatter)
      if(times.getMillis >= oldEqTime.getMillis){
        jedis.hset(key, field, dateTime)
      }
      }catch {
        case e:Exception => error(s"最后上线时间日期格式不对:${lastOnlineGpsStr}, ${dateTime}")
      }
    }else{
      jedis.hset(key, field, dateTime)
    }
  }

  /**
    * 组装报警信息
    * @param warnTypeCode
    * @param warnTypeName
    * @param drivingTime
    * @param customAlarmEvidence
    * @param warnTypeCodes
    * @param esList
    * @param vehicleAlarmEvidences
    */
  def assemblyEvidence(warnTypeCode: String,
                       warnTypeName: String,
                       drivingTime:Int,
                       customAlarmEvidence: CustomAlarmEvidence,
                       warnTypeCodes: ListBuffer[String],
                       esList: ListBuffer[(String, String)],
                       vehicleAlarmEvidences: ListBuffer[VehicleAlarmEvidence]): Unit ={
    val alarmMap = createAlarmMap(warnTypeCode, warnTypeName, customAlarmEvidence)
    val id = customAlarmEvidence.primaryKey + "_" + warnTypeCode + "_" + customAlarmEvidence.datetime
    esList += ((id, MapToJson.Map2Josn(alarmMap)))
    warnTypeCodes += (warnTypeCode)

    //缓存报警证据
    val evidence = AlarmEvidence(id, customAlarmEvidence.datetime, drivingTime)
    val evidences = new util.ArrayList[AlarmEvidence]()
    evidences.add(evidence)
    vehicleAlarmEvidences.append(VehicleAlarmEvidence(warnTypeCode, evidences))
  }

  /**
    * 组装报警信息,有效性报警，包含驾驶时长和行驶里程
    * @param warnTypeCode
    * @param warnTypeName
    * @param drivingTime
    * @param customAlarmEvidence
    * @param warnTypeCodes
    * @param esList
    * @param vehicleAlarmEvidences
    * @param drivingDuration
    * @param drivingMileage
    */
  def assemblyEvidence(warnTypeCode: String,
                        warnTypeName: String,
                        drivingTime:Int,
                        customAlarmEvidence: CustomAlarmEvidence,
                        warnTypeCodes: ListBuffer[String],
                        esList: ListBuffer[(String, String)],
                        vehicleAlarmEvidences: ListBuffer[VehicleAlarmEvidence],
                        drivingDuration: String,
                        drivingMileage: String): Unit ={
    val alarmMap = createAlarmMap(warnTypeCode, warnTypeName, customAlarmEvidence)
    //行驶时长
    alarmMap.put("drivingDuration", drivingDuration)
    //行驶里程
    alarmMap.put("drivingMileage", drivingMileage)
    val id = customAlarmEvidence.primaryKey + "_" + warnTypeCode + "_" + customAlarmEvidence.datetime
    esList += ((id, MapToJson.Map2Josn(alarmMap)))
    warnTypeCodes += (warnTypeCode)

    //缓存报警证据
    val evidence = AlarmEvidence(id, customAlarmEvidence.datetime, drivingTime)
    val evidences = new util.ArrayList[AlarmEvidence]()
    evidences.add(evidence)
    vehicleAlarmEvidences.append(VehicleAlarmEvidence(warnTypeCode, evidences))
  }

  /**
    * 组装报警信息
    * @param warnTypeCode
    * @param warnTypeName
    * @param drivingTime
    * @param customAlarmEvidences
    * @param warnTypeCodes
    * @param esList
    * @param vehicleAlarmEvidences
    */
  def assemblyEvidence(warnTypeCode: String,
                       warnTypeName: String,
                       drivingTime:Int,
                       customAlarmEvidences: List[CustomAlarmEvidence],
                       warnTypeCodes: ListBuffer[String],
                       esList: ListBuffer[(String, String)],
                       vehicleAlarmEvidences: ListBuffer[VehicleAlarmEvidence]): Unit ={
    if(customAlarmEvidences.nonEmpty){
      val evidences = new util.ArrayList[AlarmEvidence]()
      customAlarmEvidences.foreach{customAlarmEvidence =>
        val alarmMap = createAlarmMap(warnTypeCode, warnTypeName, customAlarmEvidence)
        val id = customAlarmEvidence.primaryKey + "_" + warnTypeCode + "_" + customAlarmEvidence.datetime
        esList += ((id, MapToJson.Map2Josn(alarmMap)))
        val evidence = AlarmEvidence(id, customAlarmEvidence.datetime, drivingTime)
        evidences.add(evidence)
      }
      //缓存报警证据
      vehicleAlarmEvidences.append(VehicleAlarmEvidence(warnTypeCode, evidences))
      warnTypeCodes += (warnTypeCode)
    }
  }

  /**
    * 创建报警信息
    * @param warnTypeCode
    * @param warnTypeName
    * @param customAlarmEvidence
    * @return
    */
  def createAlarmMap(warnTypeCode: String, warnTypeName: String, customAlarmEvidence: CustomAlarmEvidence): util.HashMap[String, String] = {
    val esMap = new util.HashMap[String, String]()
    val warnMap = new util.HashMap[String, String]()
    val warnList = new ListBuffer[(String,String)]()
    val id = customAlarmEvidence.primaryKey + "_" + warnTypeCode + "_" + customAlarmEvidence.datetime
    val tempKey = customAlarmEvidence.primaryKey + "_" + warnTypeCode + "_" + customAlarmEvidence.tripStartMillis
    esMap.put("id", id)
    esMap.put("primaryKey", tempKey)
    esMap.put("districtCode", "-")
    esMap.put("infoId", "-")
    esMap.put("warnType", "-")
    esMap.put("eventType", "-")
    esMap.put("typeName", warnTypeName)
    esMap.put("typeCode", warnTypeCode)
    esMap.put("deviceId", "-")
    esMap.put("speed", customAlarmEvidence.speed)
    esMap.put("datetime", customAlarmEvidence.datetime)
    esMap.put("riskCodeTime", customAlarmEvidence.riskCodeTime)
    esMap.put("levelId", RiskConst.WARNING_LEVEL_FIRST)
    esMap.put("warnSrc", RiskConst.WARNING_SOURCE)
    esMap.put("warnSeq", "0")
    esMap.put("longitude", customAlarmEvidence.longitude)
    esMap.put("latitude", customAlarmEvidence.latitude)
    esMap.put("driverName", customAlarmEvidence.driverName)
    esMap.put("driverCode", customAlarmEvidence.driverCode)
    esMap.put("vehicleEnterpriseCode", customAlarmEvidence.vehicleEnterpriseCode)
    esMap.put("vehicleNo", customAlarmEvidence.vehicleNo)
    esMap.put("vehicleColor", customAlarmEvidence.vehicleColor)
    esMap.put("appId", customAlarmEvidence.appId)

    //索引alarm_details_index需要字段
    warnMap.put("id", id)
    warnMap.put("alarmId", id)
    warnMap.put("warntime", customAlarmEvidence.alarmTime)
    warnMap.put("warnsrc", RiskConst.WARNING_SOURCE)
    warnMap.put("warntype", "-")
    warnMap.put("eventtype", "-")
    warnMap.put("datatype", customAlarmEvidence.dataType)
    warnMap.put("warningtypename", warnTypeName)
    warnMap.put("warningtypecode", warnTypeCode)
    warnMap.put("infoid", new IdWorker().nextId().toString)//添加随机数据作为infoId
    warnMap.put("longitude", customAlarmEvidence.longitude)
    warnMap.put("latitude", customAlarmEvidence.latitude)
    warnMap.put("districtcode", "-")
    warnMap.put("alarmday", customAlarmEvidence.alarmTime)
    warnMap.put("drivername", customAlarmEvidence.driverName)
    warnMap.put("driverid", customAlarmEvidence.driverCode)
    warnMap.put("enterprisecode", customAlarmEvidence.vehicleEnterpriseCode)
    warnMap.put("enterprisename",customAlarmEvidence.enterpriseName)
    warnMap.put("socialcreditcode",customAlarmEvidence.socialCreditCode)
    warnMap.put("vehicleno", customAlarmEvidence.vehicleNo)
    warnMap.put("vehiclecolor", customAlarmEvidence.vehicleColor)
    warnMap.put("appid", customAlarmEvidence.appId)
    warnMap.put("businesstime",customAlarmEvidence.businessTime)
    warnMap.put("usenature",customAlarmEvidence.useNature)
    warnMap.put("platformname",customAlarmEvidence.platformName)

    warnList += ((id, MapToJson.Map2Josn(warnMap)))

    EsUtils.insertBulk("alarm_details_index", "alarm_details_type", warnList)

    esMap
  }

  /**
    * 上次连续超速的报警信息
    * @param lastLocation
    * @param primaryKey
    * @param vehicleNo
    * @param vehicleColor
    * @param driverName
    * @param driverCode
    * @param vehicleEnterpriseCode
    * @param tripStartMillis
    * @return
    */
  def lastCustomAlarmEvidence(lastLocation: JSONObject, primaryKey: String, vehicleNo: String, vehicleColor: String,
                              driverName: String, driverCode: String, vehicleEnterpriseCode: String,
                              appId:String, socialCreditCode:String, enterpriseName:String,dataType: String,alarmTime: String, businessTime: String, useNature: String,platformName: String,
                              tripStartMillis: Long): CustomAlarmEvidence ={
    val date: DateTime = DateTime.parse(lastLocation.getString("dateTime"), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
    val warnTime: Long = date.toDate.getTime
    val time: String = getRiskCodeTime(warnTime)
    val datetime = (warnTime / 1000).toString

    val lng = lastLocation.getString("lon").toDouble * 0.000001
    val lat = lastLocation.getString("lat").toDouble * 0.000001
    //WGS84(地球坐标系)转GCj02(火星坐标系)
    val transform = TransformUtils.wgs84togcj02(lng, lat)
    val longitude = transform._1.formatted("%.6f")
    val latitude = transform._2.formatted("%.6f")
    val speed = lastLocation.getString("vec1")

    CustomAlarmEvidence(primaryKey, vehicleNo, vehicleColor, longitude, latitude, speed, driverName, driverCode, vehicleEnterpriseCode,
      datetime, time, appId, socialCreditCode, enterpriseName ,dataType, alarmTime, businessTime, useNature,platformName, tripStartMillis)
  }

}
